// BIOS中断大全 https://blog.nowcoder.net/n/25e6184ce87d44e1b2c40a4e8511e487
#include "kprint.h"
void kprintf_nl()
{
    asm volatile("int $0x10"
                 :
                 : "a"(0x0e0d));//回车

    asm volatile("int $0x10"
                 :
                 : "a"(0x0e0a));//换行

    // uint16_t position = getCursorPosition();

    // setCursorPosition(0, (position & 0xff00) + 1);

    return;
}

void kprintf(const char *string)
{
    while (*string)
    {
        if (*string == '\n')
        {
            kprintf_nl();
        }
        else
        {
            asm("int $0x10"
                :
                : "a"((0x0e << 8) | *string) /* AH = 0x0e, AL = char to print */
            );
        }
        string++;
    }
    return;
}

void kprintf_int(uint32_t value, int size_of)
{
    char prefix[] = {"0x"};
    kprintf(prefix);
    size_of *= 2;
    const int len = 16 + 1;
    char mes[len]; //4 bit for a char, assume sizeof(unsigned int) is 32bit
    for (int i = 0; i < size_of; i++)
        mes[i] = '0';
    mes[size_of] = '\0';
    int i = size_of - 1;
    while (i >= 0 && value != 0)
    {
        mes[i] += value & (unsigned int)0x0f;
        if (mes[i] > '9')
        {
            mes[i] += 'a' - '0' - 10;
        }
        i--;
        value >>= 4;
    }
    kprintf(mes);
    return;
}

void clearScreen()
{
    asm volatile("int $0x10"
                 :
                 : "a"(0x0700),
                   "b"(0x0700), // character attribute = white on black
                   "c"(0x0),
                   "d"(0x184f)); //设置成25行，80列, [0, 24], [0, 79]
    return;
}

void setCursorPosition(uint16_t col, uint16_t row)
{
    //设置光标
    asm volatile("int $0x10"
                 :
                 : "a"(0x0200),
                   "b"(0),
                   "d"(((row << 8) | col) & 0xffff));
}

/**
 * @brief 获取光标所在位置
 * @return unsigned int 低8位表示列号，高8位表示行号
*/
uint16_t getCursorPosition()
{
    unsigned int position;
    asm volatile("int $0x10"
                 : "=d"(position) //DH是行，DL是列
                 : "a"(0x0300));
    return position;
}